home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / 3Dmodeling / 3Dmodeler.doc < prev    next >
Encoding:
Text File  |  1994-08-02  |  14.0 KB  |  336 lines

  1.  
  2.  
  3.                 MODELER'S LITTLE HELPER
  4.                      Tom Davis
  5.  
  6.  
  7.  
  8.                     INTRODUCTION
  9.  
  10.     The files here generate a library of 3D modelling commands.  In
  11.     addition, there is a sample program that illustrates many of the
  12.     modelling commands in action.
  13.     
  14.     To see some samples of objects that are easily constructed using the
  15.     minimod tools, run the program called example.  The left mouse
  16.     manipulates the object in a track-ball manner, and the right mouse
  17.     brings up the pop-up menu to change models and materials.
  18.     
  19.     The idea is very simple.  There are library routines that build many
  20.     simple shapes -- platonic solids, cylinders, spheres, worms, donuts,
  21.     ...  Each routine generates a set of triangles or quadrilaterals at the
  22.     lowest level and executes a call-back procedure for each one.  You
  23.     provide the call-back function, and it can do anything it wants with
  24.     the data.  The vertices and normals for each triangle or quadrilateral
  25.     are provided to the call-back procedure.
  26.     
  27.     For example, suppose you want to draw a sphere approximated by
  28.     triangles exactly once, and never use the data again.  Then the
  29.     call-back function would take each triangle returned and draw it using
  30.     graphics library routines.  More often, however, the data will be saved
  31.     in some internal database or display list for rapid re-display.  You
  32.     could also make the call-back function dump the data into some sort of
  33.     file, or whatever you want.
  34.     
  35.     In addition to the routines that generate simple shapes, the library
  36.     also maintains a matrix transformation stack similar to that in the GL
  37.     so that transformations can be applied to the generated solids.  The
  38.     transformation takes normal information into account, even when
  39.     non-uniform scales or shearing is applied.
  40.     
  41.     The interfaces are not all consistent with each other, as each was
  42.     invented as needed.  Some have information about centers and radii
  43.     since they were written before the general transformation routines
  44.     were available.  There's tons of stuff that could be added.  I'm
  45.     interested in contributions and suggestions.
  46.     
  47.            THE STRUCTURE OF THE CALL-BACK PROCEDURE
  48.  
  49.     The user-supplied call-back procedure must have 9 parameters.  The
  50.     first is a long, and indicates whether the following data is for a
  51.     triangle or a quadrilateral.  The next eight are pointers to arrays of
  52.     3 floats in the order n0, v0, n1, v1, n2, v2, n3, v3.  The n's stand
  53.     for normal vectors and the v's for vertices.  If a triangle is passed
  54.     back as indicated by the first parameter, the contents of n3 and v3 may
  55.     be garbage.  The first parameter to the call-back routine is either
  56.     ADD_QUAD or ADD_TRI (defined in the file 3d.h).
  57.  
  58.                  PRIMITIVE MODELING ROUTINES
  59.  
  60.     Primitive modelling routines (in all cases, the function savefunc is
  61.     the call-back routine):
  62.  
  63. void drawbox(float x0, float x1, float y0, float y1,
  64.                 float z0, float z1, void (*savefunc)());
  65.  
  66.     Makes a rectangular box from x0 to x1 in the x-direction, and so on.
  67.  
  68. void quadsphere(long latsides, long longsides, void (*savefunc)());
  69.  
  70.     Approximates a sphere with quadrilaterals, using the parameters
  71.     for the number of latitude and longitude lines.
  72.  
  73. void trisphere(float *center, float radius, long depth, void (*savefunc)());
  74.  
  75.     Approximates a sphere from triangles with the given center and
  76.     radius.  Depth is a measure of the amount of subdivision done.
  77.     A depth of one corresponds to an icosahedron, a depth of 2
  78.     divides each triangle into 4 pieces, depth 3 => 9 pieces, and
  79.     depth n => n^2 pieces, so for a sphere at depth n, there will
  80.     be 20*n^2 triangles.  center is a pointer to the first of three
  81.     floats.
  82.  
  83. void doughnut(float r, float R, long nsides, long rings, void (*savefunc)());
  84.  
  85.     Makes a torus (doughnut) with a tube of radius r centered around
  86.     a circle of radius R in the x-y plane.  The circle is divided into
  87.     rings divisions, and around each ring there are nsides sides.
  88.  
  89. void elbow(float *p0, float *p1, float *p2,
  90.         float radius, long nsides, long nsegs, void (*savefunc)());
  91.  
  92.     Makes a 90 degree elbow, centered at p0, and going from p1 to p2.
  93.     The radius is given, as well as the number of segments and sides
  94.     making up the elbow.  p0, p1, and p2 are pointers to sets of 3
  95.     floats.
  96.  
  97. void cylinder(float *p1, float *p2,
  98.             float radius, long nsides, void (*savefunc)());
  99.  
  100.     Makes a cylinder about the line segment connecting p1 to p2 having
  101.     the given radius and number of sides.  p1 and p2 are pointers to
  102.     sets of 3 floats.
  103.  
  104. void icosahedron(float *center, float r, void (*savefunc)());
  105. void octahedron(float *center, float r, void (*savefunc)());
  106. void tetrahedron(float *center, float r, void (*savefunc)());
  107. void dodecahedron(float *center, float r, void (*savefunc)());
  108.  
  109.     These routines make the corresponding platonic solids, centered
  110.     at center, and having the given "radius".  (I may have the
  111.     radius wrong sometimes, but bigger numbers do make them bigger,
  112.     and if the radii are about the same, the solids are about the
  113.     same size.)
  114.  
  115.             CURVES: SMOOTH AND PIECEWISE LINEAR
  116.  
  117.     Some modelling routines use curves to construct objects.  The
  118.     constructed objects can be worms made by sweeping circles or other
  119.     curves along curves, or solids of revolution.  At present, there is no
  120.     way to use the curve or piecewise linear curve information in any other
  121.     way.  The simplest curves are just piecewise linear curves, made by the
  122.     routine:
  123.  
  124. pwlin_t *makepwlin(long n, float *p);
  125.  
  126.     The number of (3-d) points along the curve is given by n, and p
  127.     is a pointer to a list of 3*n floats.  A pointer to a structure
  128.     is returned that represents the piecewise linear curve.
  129.  
  130. void    freepwlin(pwlin *pw);
  131.  
  132.     This routine frees a piecewise linear curve generated by makepwlin().
  133.  
  134. pwlin_t *appendpwlins(pwlin_t *pw1, pwlin_t *pw2);
  135.  
  136.     This routine appends two piecewise linear curves by attaching
  137.     the end of pw1 to the beginning of pw2.  The piecewise linear
  138.     curve returned is different from pw1 and pw2, which are
  139.     unaffected.  If the final point of pw1 is equal to the initial
  140.     point of pw2, the duplicate is eliminated; otherwise, the two
  141.     are just connected by a line segment.
  142.  
  143.     Curves are saved as an analytic representation, and are basically
  144.     converted to piecewise linear form internally whenever necessary.  It
  145.     probably would have been better to make curves and piecewise liner
  146.     curves one object, but I didn't.  There would have been a few ugly
  147.     problems.
  148.  
  149. curve_t *newcubiccurve(float *p1, float *p2, float *p3, float *p4);
  150. curve_t *newbeziercurve(float *p1, float *p2, float *p3, float *p4);
  151. curve_t *newbsplinecurve(float *p1, float *p2, float *p3, float *p4);
  152. curve_t *newcardinalcurve(float *p1, float *p2, float *p3, float *p4);
  153.  
  154.     These four routines return a pointer to a curve structure where
  155.     the curves are all cubic splines based on the four given
  156.     control points.  The independent variable is assumed to run
  157.     from 0 to 1.
  158.  
  159. curve_t *newanalyticcurve(float (*x)(float), float (*y)(float), float (*z)(float),
  160.         float (*dx)(float), float (*dy)(float), float (*dz)(float),
  161.         float (*ddx)(float), float (*ddy)(float), float (*ddz)(float));
  162.  
  163.     An arbitrary analytic curve can be specified (for the
  164.     independent variable running from 0.0 to 1.0.  You must give
  165.     functions for the x, y, and z coordinates as well as the
  166.     analytic derivatives and second derivatives of the functions
  167.     (with respect to the independent variable).
  168.  
  169. pwlin_t    *pwlinfromcurve(curve_t *c, long nsteps);
  170.  
  171.     This routine lets you make a piecewise linear curve from an
  172.     analytic curve with the given number of steps.  For now, it
  173.     just takes nsteps uniform steps between 0.0 and 1.0.
  174.  
  175.                           USING THE CURVE ROUTINES
  176.  
  177. void makeworm(curve_t *c, float radius, long nsides,
  178.                 long nsegs, void (*savefunc)());
  179.  
  180.     Given a curve c, this routine generates a worm made by sweeping a
  181.     circle along the curve and perpendicular to it.  The circle has
  182.     the given radius, and is approxiamted by a polygon with nsides.
  183.     nsegs evenly spaced points along the curve are used.
  184.  
  185. void makepwlworm(curve_t *c, pwlin_t *p, long nsteps, void (*savefunc)());
  186.  
  187.     If you want a shape other than a circle to be swept along the
  188.     curve c, make an appropriate piecewise linear shape in the x-y
  189.     plane, and pass it to this routine as the second parameter.  The
  190.     piecewise linear curve will be placed nsteps times along the
  191.     curve and perpendicular to it, and corresponding points will be
  192.     connected.  The resulting worm will look faceted -- i.e. the
  193.     normals will the perpendicular to the faces.
  194.  
  195. void makesmoothpwlworm(curve_t *c, pwlin_t *p, long nsteps, void (*savefunc)());
  196.  
  197.     The same as the routine above, except that the normals at each
  198.     facet intersection will be averaged to give a smooth worm.
  199.  
  200. void solidofrevolution(pwlin_t *p, long nsteps, void (*savefunc)());
  201. void smoothsolidofrevolution(pwlin_t *p, long nsteps, void (*savefunc)());
  202.  
  203.     Both these routines sweep a piecewise linear curve about the y-axis
  204.     and form a solid of revolution with nsteps evenly spaced steps
  205.     taken around the y-axis.  The smooth version averages the facet's
  206.     normals; the regular version gives a faceted solid.
  207.  
  208.                  ANALYTIC SURFACES
  209.  
  210.     If you have a parametric surface defined in terms of:
  211.  
  212.     (x(s,t), y(s,t), z(s,t))
  213.  
  214.     and you can take the analytic partial derivatives with respect to s and t:
  215.  
  216.     (xs(s,t), ys(s,t), zs(s,t))
  217.     (xt(s,t), yt(s,t), zt(s,t))
  218.  
  219.     then to generate a surface for smin<s<smax and tmin<t<tmax, use the
  220.     function:
  221.  
  222. void analyticsurface(float (*x)(float, float), float (*y)(float, float), 
  223.              float (*z)(float, float), 
  224.              float (*xs)(float, float), float (*ys)(float, float), 
  225.              float (*zs)(float, float), 
  226.              float (*xt)(float, float), float (*yt)(float, float), 
  227.              float (*zt)(float, float), 
  228.              long scount, float smin, float smax,
  229.              long tcount, float tmin, float tmax,
  230.              long flipnormals, 
  231.              void (*savefunc)());
  232.  
  233.     x, y, z, xs, ys, zs, xt, yt, and zt are pointers to the functions
  234.     described above; scount is the number of steps to take between smin and
  235.     smax; tcount is the same thing in the t-direction, and flipnormals is
  236.     either 1 or 0, and if it's 1, all the normal vector directions are
  237.     flipped before being passed to savefunc().  savefunc() is as in any of
  238.     the other examples.
  239.  
  240.                   TRANSFORMATIONS
  241.  
  242.     The transformations are basically the same as those provided in the GL,
  243.     except that there is just a single matrix stack, there is no general
  244.     loadmatrix, multmatrix or getmatrix commands.  The only unusual call is
  245.     the shear() routine that multiplies by a shearing matrix that looks like
  246.     this:
  247.  
  248.     | 1.0  xy   xz   0.0 |
  249.     | 0.0  1.0  yz   0.0 |
  250.     | 0.0  0.0  1.0  0.0 |
  251.     | 0.0  0.0  0.0  1.0 |
  252.  
  253. void m_resetmatrixstack();
  254. void m_pushmatrix();
  255. void m_popmatrix();
  256. void m_shear(float xy, float xz, float yz);
  257. void m_translate(float tx, float ty, float tz);
  258. void m_scale(float sx, float sy, float sz);
  259. void m_rotate(float angle, char axis);
  260.  
  261.     m_resetmatrixstack() empties the stack and loads on an identity
  262.     matrix.  The m_rotate angle takes its angle parameter in radians.
  263.     (If your angle is in degrees, multiply by PI/180.0 to convert
  264.     to radians).  The character can be 'x', 'X', 'y', 'Y', 'z', or
  265.     'Z' (for the rotate command).
  266.  
  267.                  ERRORS
  268.  
  269.     If the library encounters an error, it will print out an error string
  270.     and exit.  If you don't like this behavior, you can replace the error
  271.     handler by one of your own using the routine:
  272.  
  273. void seterrorfunc(void (*func)(char *));
  274.  
  275.     Your routine func() will then be called with the same string that the
  276.     default error handler would have spit out before it died.  (Yeah, I
  277.     know it's primitive.)  Call the routine with 0 to restore the default
  278.     behavior.
  279.  
  280.                ADDITIONAL USEFUL ROUTINES
  281.  
  282.     The library has a whole set of routines for handling 3-d vectors that
  283.     are used extensively internally, and you may find them useful.  They are
  284.     listed below, and they "do the obvious thing".  All the routines work
  285.     fine if the output vector is the same as one of the input vectors.
  286.  
  287. void    diff3(float *v1, float *v2, float *v1minusv2);
  288. void    add3(float *v1, float *v2, float *v1plusv2);
  289. void    scalarmult(float s, float *v1, float *sv1);
  290. float    dot3(float *v1, float *v2);
  291. float    length3(float *v1);
  292. float    dist3(float *v1, float *v2);
  293. void    copy3(float *v1, float *copyofv1);
  294. void    crossprod(float *v1, float *v2, float *v1crossv2);
  295. void    normalize(float *v1);
  296. void    print3(float *v);
  297. void    printmat3(float m[3][3]);
  298. void    identifymat3(float m[3][3]);
  299. void    copymat3(float m[3][3], float newm[3][3]);
  300.  
  301.                 USING THE LIBRARY
  302.  
  303.     A pretty good example is given in the program example.c.  Most of the
  304.     routines are used there.  The worst thing about example.c is probably
  305.     the display list used.  I just have a giant array for triangle data
  306.     and for quad data and dump stuff into it.  To draw it, I just traverse
  307.     the data.  There's no checking for out of space, etc.
  308.  
  309.     Just be sure to include the file "3d.h", and everything should be cool.
  310.  
  311.     The example program uses a simple viewer (similar to the one in Showcase)
  312.     that moves the model with a trackball-type interface controlled by the
  313.     left mouse button.  If you click down in the green area and move the
  314.     mouse with the button down, the trackball follows.  If you click outside
  315.     the green circle, it's as if you grabbed it right on the edge.  This makes
  316.     it easy to do pure rotations about the z-axis (the axis pointing straight
  317.     into the screen).  The trackball interface is not great, but may be useful
  318.     to somebody.  It needs work.  I'm hoping to use the Scenario viewers.
  319.  
  320.              ADDING YOUR OWN MODELING ROUTINES
  321.  
  322.     This isn't very hard to do -- look at examples in the file solids.c for
  323.     some simple examples.  Note the calls to m_xformpt() at the end for
  324.     each vertex.  This applies the current transformation matrix to the
  325.     normalized data that the routine generates.
  326.  
  327.                    MISSING STUFF
  328.  
  329.     NURBS surfaces, solids of extrusion, blending, mitering, ...  Also, it
  330.     would be nice to have some routines to generate triangle meshes from the
  331.     input, etc.
  332.  
  333.  
  334.  
  335.  
  336.